#ifndef CAST_H_JM_20121129
#define CAST_H_JM_20121129

// ## c++
#include <sstream>
#include <typeinfo>

#include "NoType.h"

namespace jmlib {

	template<class From, class To>
	struct Converter {
		
		static To convert(From value, bool* ok = nullptr) {
			std::stringstream stream;
			stream << value;
			To result;
			stream >> result;
			if (stream.bad() || stream.fail()) {
				if (ok) {
					*ok = false;
				}
				else {
					throw  new std::bad_cast;
				}
				result = To();
			}
			else if (ok) {
				*ok = true;
			}
			return result;
		}
	};

	template<class From>
	struct Converter<From, NoType> {

		static NoType convert(From from, bool* ok = nullptr) {
			if (ok) {
				*ok = false;
				return NoType();
			}
			else {
				throw new std::bad_cast;
			}
		}

	};

	template<class To>
	struct Converter<NoType, To> {

		static To convert(NoType from, bool* ok = nullptr) {
			if (ok) {
				*ok = false;
				return To();
			}
			else {
				throw new std::bad_cast;
			}
		}

	};

	template<typename targetType, typename sourceType>
	targetType convert(sourceType value, bool* ok = nullptr) {
		return Converter<sourceType, targetType>::convert(value, ok);
	}


	template<typename targetType, typename sourceType>
	bool tryConvert(sourceType value) {
		bool ok = true;
		targetType target = convert<targetType>(value, &ok);
		return ok;
	}

} // namespce jmlib 

#endif
